package com.rzt.cft.service.project.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rzt.cft.constant.ServiceStatus;
import com.rzt.cft.constant.StatusConstant;
import com.rzt.cft.constant.TypeConstant;
import com.rzt.cft.utils.CustomUtil;
import com.rzt.cft.dto.ResponseData;
import com.rzt.cft.dto.uc.UcUserDto;
import com.rzt.cft.entity.project.ProjectDetail;
import com.rzt.cft.entity.project.ProjectOrder;
import com.rzt.cft.entity.project.ProjectStatistics;
import com.rzt.cft.entity.uc.UcUsable;
import com.rzt.cft.mapper.project.ProjectDetailMapper;
import com.rzt.cft.mapper.project.ProjectOrderMapper;
import com.rzt.cft.mapper.project.ProjectStatisticsMapper;
import com.rzt.cft.param.project.AddProjectDetailParam;
import com.rzt.cft.param.uc.InsertUsableParam;
import com.rzt.cft.param.uc.ProjectInjection;
import com.rzt.cft.param.uc.UcAssetStatisticsParam;
import com.rzt.cft.param.uc.UpgradeParam;
import com.rzt.cft.service.project.IProjectDetailService;
import com.rzt.cft.service.uc.IUcAssetService;
import com.rzt.cft.service.uc.IUcAssetStatisticsService;
import com.rzt.cft.service.uc.IUcUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 项目-详情表 服务实现类
 * </p>
 *
 * @author zhongzhong
 * @since 2020-03-10
 */
@Service
public class ProjectDetailServiceImpl extends ServiceImpl<ProjectDetailMapper, ProjectDetail> implements IProjectDetailService {

    @Autowired
    private ProjectStatisticsMapper projectStatisticsMapper;

    @Autowired
    private IUcAssetService ucAssetService;

    @Autowired
    private IUcAssetStatisticsService ucAssetStatisticsService;

    @Autowired
    private ProjectOrderMapper projectOrderMapper;

    @Autowired
    private IUcUserService ucUserService;

    /**
     * 利息精度
     */
    public static MathContext mc = new MathContext(6, RoundingMode.HALF_UP);

    @Override
    @Transactional
    public Boolean add(AddProjectDetailParam addProjectDetailParam) {
        ProjectDetail projectDetail = CustomUtil.maping(addProjectDetailParam, ProjectDetail.class);
        int count = baseMapper.countNum();
        String code = CustomUtil.getCode(count);
        projectDetail.setProjectSn(code);
        if (addProjectDetailParam.getType().equals(TypeConstant.projectType.OPTIONAL)) {
            BigDecimal minAmt = Collections.min(addProjectDetailParam.getSubscriptionAmounts());
            projectDetail.setPurchaseAmount(minAmt);
        }

        projectDetail.setReleaseTime(LocalDateTime.now());
        projectDetail.setStatus(StatusConstant.ProjectStatus.IN_HAND);
        if (addProjectDetailParam.getPurchasableGrades() != null && addProjectDetailParam.getPurchasableGrades().size() > 0) {
            projectDetail.setPurchasableGrade(JSONUtil.toJsonStr(addProjectDetailParam.getPurchasableGrades()));
//            List<UcDistributionType> ucDistributionTypes = ucDistributionTypeMapper.selectBatchIds(addProjectDetailParam.getPurchasableGrades());
//            if (ucDistributionTypes.size() > 0) {
//                List<DistributionTypeDto> distributionTypeDtos = CustomUtil.maping(ucDistributionTypes, DistributionTypeDto.class);
//                projectDetail.setPurchasableGrade(JSONUtil.toJsonStr(distributionTypeDtos));
//            }
        }
        if (addProjectDetailParam.getSubscriptionAmounts() != null && addProjectDetailParam.getSubscriptionAmounts().size() > 0) {
            List<BigDecimal> amounts = addProjectDetailParam.getSubscriptionAmounts();
            projectDetail.setSubscriptionAmount(JSONUtil.toJsonStr(amounts));
        }
        baseMapper.insert(projectDetail);
        ProjectStatistics projectStatistics = CustomUtil.maping(projectDetail, ProjectStatistics.class);
        projectStatistics.setId(null);
        projectStatistics.setCurrent(true);
        projectStatistics.setProjectName(projectDetail.getName());
        projectStatistics.setProjectId(projectDetail.getId());
        projectStatistics.setRaisedAmount(BigDecimal.ZERO);
        projectStatistics.setSurplus(projectDetail.getTotal());
        projectStatistics.setRealProgress(BigDecimal.ZERO);
        int result = projectStatisticsMapper.insert(projectStatistics);
        return retBool(result);
    }

    @Transactional
    @Override
    public Boolean update(AddProjectDetailParam addProjectDetailParam) {
        ProjectDetail projectDetail = CustomUtil.maping(addProjectDetailParam, ProjectDetail.class);
        if (addProjectDetailParam.getPurchasableGrades() != null && addProjectDetailParam.getPurchasableGrades().size() > 0) {
            projectDetail.setPurchasableGrade(JSONUtil.toJsonStr(addProjectDetailParam.getPurchasableGrades()));
//            List<UcDistributionType> ucDistributionTypes = ucDistributionTypeMapper.selectBatchIds(addProjectDetailParam.getPurchasableGrades());
//            if (ucDistributionTypes.size() > 0) {
//                List<DistributionTypeDto> distributionTypeDtos = CustomUtil.maping(ucDistributionTypes, DistributionTypeDto.class);
//                projectDetail.setPurchasableGrade(JSONUtil.toJsonStr(distributionTypeDtos));
//            }
        }
        if (addProjectDetailParam.getSubscriptionAmounts() != null && addProjectDetailParam.getSubscriptionAmounts().size() > 0) {
            List<BigDecimal> amounts = addProjectDetailParam.getSubscriptionAmounts();
            projectDetail.setSubscriptionAmount(JSONUtil.toJsonStr(amounts));
        }
        int count = baseMapper.updateById(projectDetail);
        QueryWrapper<ProjectStatistics> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project_id", projectDetail.getId());
        queryWrapper.eq("current", true);
        ProjectStatistics projectStatistics = projectStatisticsMapper.selectOne(queryWrapper);
        if (addProjectDetailParam.getVirtualProgress() != null) {
            projectStatistics.setVirtualProgress(projectDetail.getVirtualProgress());
        }
        if (addProjectDetailParam.getTotal() != null) {
            BigDecimal oldSurplus = projectStatistics.getSurplus();
            BigDecimal surplus = oldSurplus.subtract(projectStatistics.getTotal()).add(addProjectDetailParam.getTotal());
            projectStatistics.setSurplus(surplus);
            projectStatistics.setTotal(addProjectDetailParam.getTotal());
        }
        projectStatisticsMapper.updateById(projectStatistics);
        return retBool(count);
    }

    @Override
    @Transactional
    public synchronized ResponseData<String> capitalInjection(ProjectInjection projectInjection, UcUserDto ucUserDto, ProjectDetail projectDetail) {
        //校验剩余可投
        ProjectStatistics projectStatistics = getStatistics(projectInjection.getId());
        if (Objects.isNull(projectStatistics)) {
            return new ResponseData(ServiceStatus.PARAM_EXCEPTION);
        }
        if (projectStatistics.getSurplus().compareTo(projectInjection.getAmount()) < 0) {
            return new ResponseData(ServiceStatus.SURPLUS_DEFICIENCY);
        }
        //校验可用余额
        UcUsable ucUsable = ucAssetService.queryUsable(ucUserDto.getId());
        if (Objects.isNull(ucUsable) || ucUsable.getUsable().compareTo(projectInjection.getAmount()) < 0) {
            return new ResponseData(ServiceStatus.YOUR_CREDIT_RUNNING_LOW);
        }

        //更新项目统计
        ProjectStatistics newProjectStatistics = new ProjectStatistics();
        BigDecimal percentage = projectInjection.getAmount().divide(projectDetail.getTotal(), mc);
        newProjectStatistics.setRealProgress(projectStatistics.getRealProgress().add(percentage));
        newProjectStatistics.setVirtualProgress(projectStatistics.getVirtualProgress());
        if (projectDetail.getProgressSwitch() == 3) {
            newProjectStatistics.setVirtualProgress(projectStatistics.getVirtualProgress().add(percentage));
        }
        newProjectStatistics.setSurplus(projectStatistics.getSurplus().subtract(projectInjection.getAmount()));
        newProjectStatistics.setRaisedAmount(projectStatistics.getRaisedAmount().add(projectInjection.getAmount()));
        newProjectStatistics.setCurrent(true);
        newProjectStatistics.setProjectId(projectStatistics.getProjectId());
        newProjectStatistics.setProjectName(projectStatistics.getProjectName());
        newProjectStatistics.setType(projectStatistics.getType());
        newProjectStatistics.setProjectSn(projectStatistics.getProjectSn());
        newProjectStatistics.setTotal(projectStatistics.getTotal());

        //添加订单
        ProjectOrder projectOrder = new ProjectOrder();
        LocalDateTime injectionTime = LocalDateTime.now();
        projectOrder.setUserId(ucUserDto.getId());
        projectOrder.setAmount(projectInjection.getAmount());
        projectOrder.setInjectionTime(injectionTime);
        projectOrder.setOrderSn(CustomUtil.getSsn());
        projectOrder.setProjectId(projectDetail.getId());
        projectOrder.setProjectName(projectDetail.getName());
        projectOrder.setProjectSn(projectDetail.getProjectSn());
        projectOrder.setReleaseTime(projectDetail.getReleaseTime());
        projectOrder.setProjectType(projectDetail.getType());
        projectOrder.setStatus(StatusConstant.ProjectOrderStatus.IN_HAND);
        projectOrder.setDailyInverse(projectDetail.getDailyInverse());
        if (projectDetail.getType().equals(TypeConstant.projectType.INTELLIGENCE)) {
            projectOrder.setTerm(projectInjection.getTerm());
            if (projectInjection.getTerm().equals(TypeConstant.projectTerm.ONE_YEAR)) {
                projectOrder.setCompletionTime(injectionTime.plusDays(360));
                projectOrder.setDailyInverse(projectDetail.getYearRate());
            }
            if (projectInjection.getTerm().equals(TypeConstant.projectTerm.HALF_YEAR)) {
                projectOrder.setCompletionTime(injectionTime.plusDays(180));
                projectOrder.setDailyInverse(projectDetail.getHalfYearRate());
            }
        }
        if (projectDetail.getType().equals(TypeConstant.projectType.OPTIONAL)) {
            projectOrder.setCompletionTime(injectionTime.plusDays(1));
        }
        projectOrderMapper.insert(projectOrder);

        //减少余额
        InsertUsableParam insertUsableParam = new InsertUsableParam();
        insertUsableParam.setUserId(ucUserDto.getId());
        insertUsableParam.setUserName(ucUserDto.getNickName());
        insertUsableParam.setType(TypeConstant.usableChangeType.BALANCE_CAPITAL_INJECTION);
        insertUsableParam.setUsable(projectInjection.getAmount().negate());
        insertUsableParam.setInvestment(projectInjection.getAmount());
        insertUsableParam.setFreeze(projectInjection.getAmount());
        insertUsableParam.setRemarks(projectOrder.getId());
        ucAssetService.insertUsable(insertUsableParam);

        projectStatistics.setCurrent(false);
        projectStatisticsMapper.updateById(projectStatistics);
        newProjectStatistics.setOrderId(projectOrder.getId());
        projectStatisticsMapper.insert(newProjectStatistics);

        //更新个人资产统计信息
        UcAssetStatisticsParam ucAssetStatisticsParam = new UcAssetStatisticsParam();
        ucAssetStatisticsParam.setUserId(ucUserDto.getId());
        ucAssetStatisticsParam.setAccumulationInjection(projectInjection.getAmount());
        ucAssetStatisticsService.addAssetStatistics(ucAssetStatisticsParam);

        //校验是否可以升级
        UpgradeParam upgradeParam = new UpgradeParam();
        upgradeParam.setId(ucUserDto.getId());
        upgradeParam.setAmount(projectInjection.getAmount());
        ucUserService.moneyUpgrade(upgradeParam);

        //如果剩余可投变成0，则修改状态为已完成
        if (newProjectStatistics.getSurplus().compareTo(BigDecimal.ZERO) == 0) {
            projectDetail.setStatus(StatusConstant.ProjectStatus.COMPLETED);
            baseMapper.updateById(projectDetail);
        }

        return new ResponseData(projectOrder.getId());
    }

    /**
     * 根据项目id查询项目统计
     * @param projectId
     * @return
     */
    public ProjectStatistics getStatistics(String projectId) {
        QueryWrapper<ProjectStatistics> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project_id", projectId);
        queryWrapper.eq("current", true);
        ProjectStatistics projectStatistics = projectStatisticsMapper.selectOne(queryWrapper);
        return projectStatistics;
    }

}
